package com.kunge2013.service.registry.listener;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.zookeeper.data.Stat;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * @Author kunge2013
 * @Description TODO
 * @Date 2024/10/28 13:51
 * @Version 1.0
 */
@Component
@Slf4j
public class FoundServerListener {
    @Resource
    CuratorFramework zkClient;

    @Resource
    ApplicationContext applicationContext;

    @Order(value = 100)
    @EventListener(value = ApplicationStartedEvent.class)
    public void foundServer(ApplicationStartedEvent event) {
        log.info("foundServer init ");
        zkClient.sync();
        try {
            Environment environment = applicationContext.getEnvironment();
            String appName = environment.getProperty("spring.application.name");
            appName = "/" + appName;
            log.info("foundServer appName {}", appName);
            Stat stat = zkClient.checkExists().forPath(appName);
            log.info("foundServer stat {}", stat);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            log.info("foundServer checkExists end !");
        }
    }

    @Order(value = 99)
    @EventListener(value = ApplicationStartedEvent.class)
    public void registerServer(ApplicationStartedEvent event) {
        log.info("foundServer init ");
        zkClient.sync();
        try {
            Environment environment = applicationContext.getEnvironment();
            String appName = environment.getProperty("spring.application.name");
            appName = "/" + appName;
            Stat pathExists = zkClient.checkExists().forPath(appName);
            if (pathExists == null) {
                String state = zkClient.create().forPath(appName);
                log.info("registerServer stat {}", state);
            }
            Stat stat = zkClient.setData().forPath(appName, appName.getBytes("UTF-8"));
            log.info("registerServer appName {}", appName);
            log.info("registerServer stat {}", stat);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            log.info("registerServer checkExists end !");
        }
    }

    @Order(value = 99)
    @EventListener(value = ApplicationStartedEvent.class)
    public void nodeCache(ApplicationStartedEvent event) throws Exception {
        log.info("。。。。。。。。。。。。。容器初始化完毕。。。。。。。。。。。。。。");
        String path = "/ahao/watcher";
        TimeUnit.SECONDS.sleep(3);

        // 创建NodeCache对象
        NodeCache nodeCache = new NodeCache(zkClient, path);
        // 添加监听器
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                ChildData currentData = nodeCache.getCurrentData();
                if (currentData != null){
                    String s = new String(currentData.getData(), StandardCharsets.UTF_8);
                    log.info("监听{}节点发生变化，数据内容：{}",path,s);
                }else {
                    log.info("监听{}节点被删除了",path);
                }
            }
        });
        // 开启监听
        nodeCache.start();

        TimeUnit.SECONDS.sleep(2);
        if (zkClient.checkExists().forPath(path) == null) {
            // 创建节点
            zkClient.create().creatingParentsIfNeeded().forPath(path,"第一次新增".getBytes(StandardCharsets.UTF_8));
            TimeUnit.SECONDS.sleep(2);
        }
        // 更新节点
        zkClient.setData().forPath(path,"数据修改了".getBytes(StandardCharsets.UTF_8));
        TimeUnit.SECONDS.sleep(2);
        // 删除节点
        // zkClient.delete().deletingChildrenIfNeeded().forPath(path);
    }
}
